use bevy::color::palettes;
use bevy::color::palettes::css::WHITE;
use bevy::prelude::*;
use bevy::render::view::NoCpuCulling;
use bevy::render::render_resource::LoadOp;
use bevy_egui::egui;
use bevy_mod_billboard::Billboard;
use bevy_mod_billboard::prelude::*;
use bevy_egui::{EguiContexts, EguiPlugin, EguiRenderToImage};
use bevy_editor_cam::prelude::*;
// 引入 MeshPicking 插件

#[derive(Component)]
struct Selected(bool);

#[derive(Component)]
struct IssueUI;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(BillboardPlugin)
        .add_plugins(EguiPlugin)
        .add_plugins(MeshPickingPlugin)
        .add_plugins(DefaultEditorCamPlugins)
        .add_systems(Startup, (setup_billboard, setup_scene))
        .add_systems(Update, update_issue_ui)
        .run();
}

fn setup_billboard(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut images: ResMut<Assets<Image>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // Setup egui render target
    let image = images.add({
        let size = bevy::render::render_resource::Extent3d {
            width: 256,
            height: 256,
            depth_or_array_layers: 1,
        };
        let mut image = Image {
            data: vec![0; (size.width * size.height * 4) as usize].into(),
            ..default()
        };
        image.texture_descriptor.usage |= bevy::render::render_resource::TextureUsages::RENDER_ATTACHMENT;
        image.texture_descriptor.size = size;
        image
    });

    // Spawn egui render plane
    commands.spawn((
        BillboardTexture(Handle::clone(&image)),
        Mesh3d(meshes.add(Rectangle::from_size(Vec2::splat(1.5))).into()),
        EguiRenderToImage::new(image),
        Transform::from_xyz(0., 2., -0.00),  // Position it slightly in front of the billboard
        IssueUI,
        Visibility::Hidden,
        BillboardDepth(false),
    ));

    // Spawn billboard
    let image_handle = asset_server.load("issue.png");
    commands.spawn((
        BillboardTexture(image_handle.clone()),
        Mesh3d(meshes.add(Rectangle::from_size(Vec2::splat(1.0))).into()),
        Transform::from_xyz(0., 1., 0.),
        Selected(false),
        BillboardDepth(false),
    ))
    .insert(ConstantScreenSizeBillboard {
        screen_height_ratio: 0.1,
        initial_world_size: 10.0,
    })
    .observe(on_click_billboard);
}

fn update_issue_ui(
    mut ctx: Query<&mut bevy_egui::EguiContext, With<EguiRenderToImage>>,
) {
    if let Ok(mut ctx) = ctx.single_mut() {
        let mut open = true;
        egui::Window::new("Issue Details").default_open(true).show(ctx.get_mut(), |ui| {
            ui.heading("Issue #123");
            ui.label("Status: Open");
            ui.label("Priority: High");
            ui.separator();
            ui.label("Description:");
            ui.label("Description:");
            ui.label("Description:");
            ui.label("Description:");
            ui.label("This is a sample issue description.\nIt can contain multiple lines of text.");
            if ui.button("Close Issue").clicked() {
                // Handle close action
            }
        });
    }
}

fn on_click_billboard(
    click: Trigger<Pointer<Click>>,
    mut commands: Commands,
    mut query: Query<(Entity, &mut BillboardTexture, &mut Selected)>,
    mut ui_query: Query<&mut Visibility, With<IssueUI>>,
    asset_server: Res<AssetServer>,
) {
    if let Ok((entity, mut texture, mut selected)) = query.get_mut(click.target()) {
        selected.0 = !selected.0;
        let new_texture = if selected.0 {
            asset_server.load("select_issue.png")
        } else {
            asset_server.load("issue.png")
        };
        texture.0 = new_texture;

        // Toggle UI visibility
        if let Ok(mut visibility) = ui_query.single_mut() {
            *visibility = if selected.0 {
                Visibility::Visible
            } else {
                Visibility::Hidden
            };
        }
    }
}

#[derive(Component)]
#[require(Transform)]
pub struct CameraHolder;

fn setup_scene(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut config_store: ResMut<GizmoConfigStore>,
) {
    // Camera setup with editor cam
    commands.spawn((
        Camera3d::default(),
        BillboardAttachedCamera,
        Transform::from_xyz(0.0, 1.0, 20.0).looking_at(Vec3::new(0., 1., 10.), Vec3::Y),
        EditorCam::default(),
    ));

    // Light setup
    commands.spawn(DirectionalLight {
        illuminance: 10_000.0,
        shadows_enabled: true,
        ..default()
    });

    config_store.config_mut::<AabbGizmoConfigGroup>().1.draw_all = true;

    commands.insert_resource(AmbientLight {
        color: WHITE.into(),
        brightness: 0.2,
        ..default()
    });
}

// 点击 Cuboid 时的处理函数
fn on_click_cube(click: Trigger<Pointer<Click>>) {
    println!("Cuboid clicked! Target entity id: {:?}", click.target());
}